from flask import Flask, render_template, request, redirect, flash
from flask.helpers import url_for
from flask_wtf import FlaskForm
from flask_login import login_user, LoginManager, UserMixin, current_user, login_required
from wtforms import StringField, PasswordField, SelectField, SubmitField
from wtforms.validators import DataRequired

from sql import database
from config import SECRETKEY
#创建Flask对象app并初始化
app = Flask(__name__)

# 为了使外网能够访问，将host设为0.0.0.0
app.config["SECRET_KEY"] = SECRETKEY

login_manager = LoginManager()  # 实例化登录管理对象
login_manager.init_app(app)  # 初始化应用
login_manager.login_view = 'login'  # 设置用户登录视图函数 endpoint




class User(UserMixin):
    """用户类"""
    def __init__(self, id):
        data = database.getUserInfoById(id)
        self.username = data[1]
        self.password = data[2]
        self.id = id

    def get_id(self):
        """获取用户ID"""
        return self.id
    
    def verify_password(self, password):
        """密码验证"""
        return hash(self.password) == hash(password)

    @staticmethod
    def get(user_id):
        """根据用户ID获取用户实体，为 login_user 方法提供支持"""
        if not user_id:
            return None
        is_user = database.isUserById(user_id)
        if is_user:
            return User(user_id)
        return None


class LoginForm(FlaskForm):
    '''
    登录表单类
    '''
    username = StringField('用户名(学号)', validators=[DataRequired()])
    password = PasswordField('密码(QQ账号)', validators=[DataRequired()])

class InsertForm(FlaskForm):
    '''
    插入课程表单类
    '''

    # QQ和stuid在后面自动加上
    name = StringField('课程名称', validators=[DataRequired('请填写课程名称')])
    day = SelectField('日期(周几)', choices = ['周一', '周二', '周三', '周四', '周五', '周六', '周日'])
    room = StringField('教室号', validators=[DataRequired('请填写教室号')])
    teacher = StringField('教师', validators=[DataRequired('请填写教师姓名')])
    week = StringField('周次(第几周,写入全部周次)', validators=[DataRequired('请填写周次')])
    section = SelectField('节次(第几节)', choices = ['第一节（1-2）', '第二节（3-4）', '第三节（5-6）', '第四节（7-8）', '第五节（9-10）'])
    submit = SubmitField("提交")



@login_manager.user_loader
def load_user(user_id):
    return User.get(user_id)



#通过python装饰器的方法定义路由地址
@app.route("/")
@login_required
#定义方法 用jinjia2引擎来渲染页面，并返回一个index.html页面
def index():
    # index.html放在templates文件夹下才能被找到
    return render_template("index.html", username=current_user.username)



@app.route('/login', methods=('GET', 'POST'))
def login():
    '''
    用户登录
    '''
    form = LoginForm()
    emsg = None
    if form.validate_on_submit():
        username = form.username.data
        password = form.password.data
        is_user = database.isUser(username)
        if not is_user:
            emsg = "用户名有误"
        else:
            user = User(database.getId(username))  # 创建用户实体
            if user.verify_password(password):
                login_user(user)
                next = request.args.get('next')
                return redirect(next or url_for('index'))
            else:
                emsg = "密码有误"
            '''
            # is_safe_url 用来检查url是否可以安全的重定向。
            # 有关示例，参见 http://flask.pocoo.org/snippets/62/ 。
            if not is_safe_url(next):
                return flask.abort(400)
            '''
                
    return render_template('login.html', form=form, emsg=emsg)


@app.route('/select')
@login_required
def selectClass():
    '''
    查询全部课程
    '''
    return render_template('select.html', qq = current_user.password)


@app.route('/insert', methods=('GET', 'POST'))
@login_required
def insertClass():
    '''
    手动插入课程
    '''
    info = ''
    form = InsertForm()
    if request.method == 'POST':
        if form.validate() == False:
            flash('All fields are required.')
            return render_template('insert.html',form = form)
        else:
            # 在这里将网页获取的信息存放进数据库中,并且要加上QQ和stuid两个信息
            name = form.name.data
            day = changeDay(form.day.data)
            room = form.room.data
            teacher = form.teacher.data
            week = form.week.data.replace('，', ',')
            section = changeJieci(form.section.data)
            qq = current_user.password
            stuid = current_user.username
            database.insertClass(name = name, day = day, room = room, teacher = teacher, week = week, section = section, stuid = stuid, qq = qq)
            info = '成功添加课程信息'
            return render_template('insert.html', form = form, info = info)
    else:
        return render_template('insert.html', form = form, info = info)
    

@app.route('/check', methods=['GET', 'POST'])
@login_required
def check():
    '''
    查询按钮查询数据库中课程
    '''
    labels = ['ID', '学号', '课程名称', '教师', '教室', '周次', '日期（周几）', '节次（第几节）', 'QQ']
    content = database.getAllClass(current_user.username)
    return render_template('select.html', labels = labels, content = content, qq = current_user.password)

@app.route('/redirectInsert')
@login_required
def redirectInsert():
    '''
    重定向到插入课程页面
    '''
    return redirect('insert')

@app.route('/redirectSelect')
@login_required
def redirectSelect():
    '''
    重定向到查询课程页面
    '''
    return redirect('select')

@app.route('/redirectIndex')
@login_required
def redirectIndex():
    '''
    重定向到主页
    '''
    return redirect('/')




def changeJieci(jieci:str) -> int:
    '''
    将前端的字符串转为能存放进数据库的int类型,转换节次
    '''
    if jieci == '第一节（1-2）':
        return 1
    elif jieci == '第二节（3-4）':
        return 2
    elif jieci == '第三节（5-6）':
        return 3
    elif jieci == '第四节（7-8）':
        return 4
    elif jieci == '第五节（9-10）':
        return 5
    else:
        return 0

def changeDay(day:str) -> int:
    '''
    将前端的字符串转为能存放进数据库的int类型,转换日期
    '''
    if day == '周一':
        return 1
    elif day == '周二':
        return 2
    elif day == '周三':
        return 3
    elif day == '周四':
        return 4
    elif day == '周五':
        return 5
    elif day == '周六':
        return 6
    elif day == '周日':
        return 7
    else:
        return 0

if __name__ == '__main__':
    app.run(host = "0.0.0.0", port = 37373)